package jehc.cloud.oauth.client.service.impl;
import jehc.cloud.common.base.BaseHttpSessionEntity;
import jehc.cloud.common.base.BaseResult;
import jehc.cloud.common.constant.PathConstant;
import jehc.cloud.common.constant.StatusConstant;
import jehc.cloud.common.entity.InputEntity;
import jehc.cloud.common.entity.OauthAccountEntity;
import jehc.cloud.common.entity.OauthAdminSysEntity;
import jehc.cloud.common.util.JsonUtil;
import jehc.cloud.common.util.RestTemplateUtil;
import jehc.cloud.common.util.StringUtil;
import jehc.cloud.oauth.client.constant.Constant;
import jehc.cloud.oauth.client.service.AuthService;
import jehc.cloud.oauth.client.service.PushService;
import jehc.cloud.oauth.client.util.OauthAttributesUtil;
import jehc.cloud.oauth.client.util.SysModeAttributesUtil;
import jehc.cloud.oauth.client.vo.Token;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
/**
 * @Desc 客户端鉴权
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Service
@Slf4j
public class AuthServiceImpl implements AuthService {
    @Autowired
    OauthAttributesUtil oauthAttributesUtil;

    @Autowired
    PushService pushService;

    @Autowired
    RestTemplateUtil restTemplateUtil;

    @Autowired
    SysModeAttributesUtil sysModeAttributesUtil;


    /**
     * 验证权限
     * @param
     */
    public BaseResult oauth(HttpServletRequest request,InputEntity inputEntity){
        long beginTime = System.currentTimeMillis();
        if(StringUtil.isEmpty(inputEntity.getToken())){
            return new BaseResult("未能获取到客户端Token",false);
        }
        BaseResult baseResult = validateSys(request);

        logTime(beginTime,inputEntity.getUrl(),request);

        if(!baseResult.getSuccess()){
            return baseResult;
        }
        ///////////////////拦截IP黑户开始（优先级最高）///////////////////////
//        if(!validateIP(request)) {
//            if(!bDownLoad(request)){
//                return outAudStr(false,  StatusConstant.BDOWNFLAG_TEXT);
//            }
//            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_001,null,false);
//        }
        ///////////////////拦截IP黑户结束///////////////////////
        String requestUrl = inputEntity.getUrl();
        if(requestUrl.equals(PathConstant.REQUEST_ERROR)){
            return new BaseResult("Request exception",false);
        }

        //不需要登陆验证的URL
        //需要登录验证的URL（目前不使用该注解 若authUneedLogin不需要登录不满足 则其下所有方法必须默认为需登录条件）
//		AuthNeedLogin authNeedLogin=methodHandler.getMethodAnnotation(AuthNeedLogin.class);
        //如果获取到方法是无需登录则放开 让其走（优先级第二）
        if(!StringUtil.isEmpty(inputEntity.getAuthUneedLogin())){
            return new BaseResult("AuthUneedLogin---Success",true);
        }

        BaseHttpSessionEntity baseHttpSessionEntity = oauthAttributesUtil.get(inputEntity.getToken());

        baseHttpSessionEntity = pull(baseHttpSessionEntity,request,inputEntity);

        //过滤druid
        if(((requestUrl.indexOf(("druid"))> 0 ) && null == baseHttpSessionEntity)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_888,"druid被访问时，session不存在",false);
        }

        //需要登录但无需拦截验证URL
        if(!StringUtil.isEmpty(inputEntity.getNeedLoginUnAuth())){
            //如果注解为需要用户登录 则判断该用户是否登录 如果登录了 则放开其操作该方法的权限 否则不通过
            if(null == baseHttpSessionEntity){
                logTime(beginTime,inputEntity.getUrl(),request);
                return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_888,"session不存在",false);
            }else{
                //更新Token失效时间
                pushService.put(inputEntity.getToken(),new Token(baseHttpSessionEntity.getOauthAccountEntity().getAccount_id(),true));
                logTime(beginTime,inputEntity.getUrl(),request);
                return new BaseResult("NeedLoginUnAuth---Success",true);
            }
        }
        //验证当前用户是否登录（优先级第三）
        if(null == baseHttpSessionEntity){
            //未登陆Token不存在
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_888,"登陆会话失效",false);
        }

        //////////////////对功能进行拦截开始///////////////////
        //更新Token失效时间
        pushService.put(inputEntity.getToken(),new Token(baseHttpSessionEntity.getOauthAccountEntity().getAccount_id(),true));

        //如果超级管理员则放过所有功能
        if(isAdmin(baseHttpSessionEntity)){
            logTime(beginTime,inputEntity.getUrl(),request);
            return new BaseResult("Admin---Success",true);
        }
        //非超级管理员则进行功能权限验证
        Map<String,String> oauthFunctionInfoUrlMap = baseHttpSessionEntity.getOauthFunctionInfoUrlMap();
        if(null == oauthFunctionInfoUrlMap.get(requestUrl)){
            logTime(beginTime,inputEntity.getUrl(),request);
            //如果非附件操作权限
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_777,"无权限",false);
        }else{
            baseResult = dataAuth(request, requestUrl,baseHttpSessionEntity);
            logTime(beginTime,inputEntity.getUrl(),request);
            return baseResult;
        }
        //////////////////对功能进行拦截结束///////////////////
    }



    /**
     * 处理数据权限
     * @param request
     * @param requestUrl
     * @return
     * @throws
     */
    public BaseResult dataAuth(HttpServletRequest request,String requestUrl, BaseHttpSessionEntity baseHttpSessionEntity){
        String[] paramNames = (String[])request.getParameterValues("systemUID");//唯一标志systemUID
        List<String> systemUandM = baseHttpSessionEntity.getSystemAM();
        List<String> sysUID = new ArrayList<String>();
        //如果系统唯一标志不为空 说明系统采用了数据权限
        if(null != paramNames){
            //参数组成的数组
            String systemUID = paramNames[0];
            String[] systemUIDarray = new String[]{};
            if(null != systemUID && !"".equals(systemUID)){
                systemUIDarray = systemUID.split(",");
            }
            if(null != systemUandM){
                int result = 0;
                for(String str:systemUandM){
                    String[] sysUandMarray = new String[]{};
                    if(!StringUtil.isEmpty(str)){
                        sysUandMarray = str.split("#");
                        if(null != sysUandMarray){
                            //判断方法和参数都匹配
                            if(("@"+sysUandMarray[1]+"@").indexOf("@"+requestUrl+"@") >= 0){
                                for(int j = 0; j<systemUIDarray.length;j++){
                                    if(sysUandMarray[0].equals(systemUIDarray[j])){
                                        //如果相等
                                        result = result+1;
                                    }
                                }
                            }
                        }
                    }
                }
                //如果参数全部符合则进入方法
                if(result != systemUIDarray.length){
                    //没有权限操作
                    return new BaseResult("您没有该操作权限,请与管理员联系!",false);
                }
            }
        }else{
            //否则过滤当前操作是否数据权限查询拦截
            //说明可能是第一次初始化读取数据
            if(null != systemUandM){
                for(String str: systemUandM){
                    String[] sysUandMarray = new String[]{};
                    if(!StringUtil.isEmpty(str)){
                        sysUandMarray = str.split("#");
                        if(("@"+sysUandMarray[1]+"@").indexOf("@"+requestUrl+"@") >= 0){
                            sysUID.add(sysUandMarray[0]);
                        }
                    }
                }
                request.setAttribute("sysUID", sysUID);//用户ID
            }
        }
        return new BaseResult("dataAuth----success!",true);
    }

    public boolean isAdmin(BaseHttpSessionEntity baseHttpSessionEntity) {
        if(null != baseHttpSessionEntity){
            OauthAccountEntity oauthAccountEntity = baseHttpSessionEntity.getOauthAccountEntity();
            List<OauthAdminSysEntity> oauthAdminSysEntities = JsonUtil.toFList(baseHttpSessionEntity.getOauthAdminSysEntities(), OauthAdminSysEntity.class);
            if (null != oauthAccountEntity && null != oauthAdminSysEntities && !oauthAdminSysEntities.isEmpty()) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }

    /**
     * 初始化拉取信息
     * @param baseHttpSessionEntity
     * @param request
     */
    public BaseHttpSessionEntity pull(BaseHttpSessionEntity baseHttpSessionEntity,HttpServletRequest request,InputEntity inputEntity){
        if(null == baseHttpSessionEntity){
            baseHttpSessionEntity = restTemplateUtil.get(restTemplateUtil.restOauthURL() + "/httpSessionEntity",BaseHttpSessionEntity.class,request);
            oauthAttributesUtil.put(inputEntity.getToken(),baseHttpSessionEntity);
        }
        return baseHttpSessionEntity;
    }

    /**
     *
     * @param request
     * @return
     */
    public BaseResult validateSys(HttpServletRequest request){
        String value = sysModeAttributesUtil.get(Constant.SYS_MODE_KEY);
        BaseResult baseResult  = new BaseResult();
        if(StringUtil.isEmpty(value)){
            baseResult = restTemplateUtil.get(restTemplateUtil.restOauthURL() + "/validateSys",BaseResult.class,request);
            if(baseResult.getSuccess()){
                sysModeAttributesUtil.put(Constant.SYS_MODE_KEY,Constant.SYS_MODE_KEY);
                return baseResult;
            }
            baseResult.setSuccess(false);
            baseResult.setMessage("未能验证平台密钥");
           return baseResult;
        }
        baseResult.setMessage("验证平台密钥合法");
        return baseResult;
    }

    /**
     *
     * @param beginTime
     * @param url
     */
    void logTime(Long beginTime,String url,HttpServletRequest request){
        log.info(url+"||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}",
                beginTime,
                System.currentTimeMillis(),
                request.getProtocol(),//获取请求协议版本
                request.getScheme(),//获取请求使用的协议名
                request.getServerName(),//获取请求URL上的主机名（内网未转发时，一般为项目部署服务器主机ip）
                request.getServerPort(),//获取请求URL上的端口号
                request.getMethod(),//获取请求的方法
                request.getLocalPort(),//获取最终接收请求的端口
                request.getLocalName(),//获取最终接收请求的主机
                request.getRemoteAddr(),//获取发送请求的客户端地址（如果经过Apache等转发，则不是真实的DCN网地址）
                request.getRemoteHost(),//获取发送请求的客户端主机名
                request.getRemotePort());//获取发送请求的客户端端口
    }
}
